
#include "rts.h"
#include "pmodel.h"
#include "camera.h"
#include "3dx.h"
#include "terrain.h"
#include "crowd_dynamics.h"
#include "audio_core.h"
#include "3d_primitives.h"

using namespace WtfRts;

class TestVehicle: public Vehicle, public WtfEngine::ICrowdMember {

	class TurretProjectileGenerator: public InstantDamageProjectile {
	public:
		TurretProjectileGenerator()
		: InstantDamageProjectile(100)
		{
		};

		void TakeShot(const WtfEngine::IRtsUnit::tRef &rMyUnit, const WtfEngine::IRtsUnit::tRef &rUnit,
									   const tVector &vFrom, const tVector &vAt)
		{
			InstantDamageProjectile::TakeShot(rMyUnit, rUnit, vFrom, vAt);
			WtfAudio::tAudioRef rBang("sfx_bang");
         (new WtfAudio::StaticWorldSound(rBang, vFrom))->Play();

			WtfEngine::Physical * pPhysical = dynamic_cast<WtfEngine::Physical *>(&*rUnit);
			if(pPhysical) {
				// Apply impulse
				pPhysical->applyImpulse((vAt - vFrom).normalize() * 10000, vAt - pPhysical->getPosition());
			};
		};
	};

	class Turret : public RayCastWeapon {
	public:
		Turret() : RayCastWeapon(RayCastWeapon::tCreationOptions(), WtfEngine::DataManager::GetInstance().Load<WtfGraphics::XModel>("media/meshes/tankTurret.x"),
			tVector()) {
				mrProjectileGenerator = new TurretProjectileGenerator();
		};
	};

	static tCreationOptions Options() {
		tCreationOptions opts;
		opts.fMass = 10000;
		return opts;
	};

public:
	TestVehicle(): Vehicle(TestVehicle::Options(), WtfEngine::DataManager::GetInstance().Load<WtfGraphics::XModel>("media/meshes/tank.x")) {
		mrAiModel = new WtfEngine::AiModels::RtsUnit::Idle();
		mrBoundingBox = new WtfGraphics::Primitives::Oblong(2.5, 1.0, 4.0);

		mfHealth = 1000;
		mfMaxHealth = 1000;

		WtfGraphics::GraphicsData::tRef rWheel = new WtfGraphics::Primitives::Cylinder(0.4, 0.25, 8);
		Orientation3D wheelOri(Orientation3D::Rotation(tVector(0, 1, 0), M_PI / 2));

		this->AddWheel(tVector(-1, -0.3, -1.5), rWheel, wheelOri, tVector(1, 0, 0), tVector(-1, 0.2, -1.5), 0.4, true);
		this->AddWheel(tVector(1, -0.3, -1.5), rWheel, wheelOri, tVector(1, 0, 0), tVector(1, 0.2, -1.5), 0.4, true);
		this->AddWheel(tVector(-1, -0.3, 1.5), rWheel, wheelOri, tVector(1, 0, 0), tVector(-1, 0.2, 1.5), 0.4);
		this->AddWheel(tVector(1, -0.3, 1.5), rWheel, wheelOri, tVector(1, 0, 0), tVector(1, 0.2, 1.5), 0.4);

		// The cannon
		AddWeapon(new Turret());

		Unit::Init();
		WtfEngine::ICrowdMember::Init();
	};

	void OnDestroy(const IProjectile::tRef& rProjectile, const Unit::tRef& rFromUnit) {
      WtfAudio::tAudioRef rDie("sfx_tank_die");
		(new WtfAudio::StaticWorldSound(rDie, getPosition()))->Play();
		Vehicle::OnDestroy(rProjectile, rFromUnit);
	};

	tPosition getPosition() const {
		return Vehicle::getPosition();
	};

	tScalar getResistance() const {
		return 1.0;
	};

	tScalar getDiscomfort(const IMobileActor::tRef& rActor, const tPosition& vPos) const {
		return 1000.0;
	};
};

void WtfRts::Test() {
	using namespace WtfEngine;
	using namespace WtfGraphics;

	//new UnitSelection();

	//(new Static(Static::tCreationOptions(), WtfEngine::DataManager::GetInstance().Load<WtfGraphics::XModel>("media/models/OilRefinery/OilRefinery.x"), new PhysicalModels::Oblong(tVector(10, 2, 10))))
	//	->setPosition(tVector(20, 0, 20));

	// Init sounds
	//DataManager::GetInstance().Set(new WtfAudio::tAudio("sfx_bang", "media/sfx/tankShot.wav"));
	//DataManager::GetInstance().Set(new WtfAudio::tAudio("sfx_tank_die", "media/sfx/tankDie.wav"));

	new Static(Static::tCreationOptions(), new Primitives::Oblong(100, 1, 100), new PhysicalModels::Oblong("", tVector(100, 1, 100)));
	//WtfGraphics::TerrainHeightMap::Test();

	(new Static(Static::tCreationOptions(), new Primitives::Oblong(8, 1, 20), new PhysicalModels::Oblong("", tVector(8, 1, 20))))
		->setOrientation(Orientation3D::Rotation(tVector(1, 0, 0), M_PI / 6));

	for(int i = 0; i < 4; i++) {
		for(int j = 0; j < (4 - i); j++) {
			(new Physical(Physical::tCreationOptions(), new Primitives::Cube(1), new PhysicalModels::Oblong("", tVector(1, 1, 1), 1)))
				->setPosition(tVector(j - 2, i + 0.5, -20));
		};
	};

	(new TestVehicle())->setPosition(tPosition(0, 5, 20));
	(new TestVehicle())->setPosition(tPosition(-5, 5, 20));
	(new TestVehicle())->setPosition(tPosition(5, 5, 20));
	(new TestVehicle())->setPosition(tPosition(10, 5, 20));
	(new TestVehicle())->setPosition(tPosition(15, 5, 20));
	(new TestVehicle())->setPosition(tPosition(20, 5, 20));
};
